package cn.yto.print.system.version;

import cn.yto.print.config.ThreadPoolManager;
import cn.yto.print.config.i18n.I18nResourceManager;
import cn.yto.print.utils.CommonUtil;
import cn.yto.print.utils.PluginInstalledUtil;
import de.felixroske.jfxsupport.GUIState;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.Event;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.util.Optional;
import java.util.function.BiConsumer;

public class DownloadPrintPlugin {

    private static final Logger logger = LogManager.getLogger(DownloadPrintPlugin.class);
    private static final I18nResourceManager I18N = I18nResourceManager.getInstance();
    private static final String DOWNLOAD_DIR = "download";
    private static final int BUFFER_SIZE = 8192; // 缓冲区大小 8KB

    /**
     * 启动下载打印组件任务
     */
    public static void startDownloadTask(String downLoadUrl, Rectangle rectangle) {
        AnchorPane parentPane = Optional.ofNullable(rectangle.getParent())
                .filter(p -> p instanceof AnchorPane)
                .map(p -> (AnchorPane) p)
                .orElseThrow(() -> new IllegalStateException("Parent is not AnchorPane"));
        Label percentLabel = createPercentLabel(parentPane);
        parentPane.getChildren().add(percentLabel);
        percentLabel.toFront();
        String pathName = CommonUtil.getCurrentDir(DOWNLOAD_DIR) + File.separator + CommonUtil.getFileNameFromUrl(downLoadUrl);

        Task<Void> downloadTask = new Task<Void>() {
            @Override
            protected Void call() {
                HttpURLConnection connection = null;
                try (InputStream in = (connection = configureSSLConnection(downLoadUrl)).getInputStream();
                     FileOutputStream out = prepareOutputStream(pathName)) {
                    downloadFile(in, out, connection.getContentLength(), this::updateProgress, rectangle, percentLabel);
                } catch (Exception e) {
                    logger.error("{} 打印组件安装程序下载异常", pathName, e);
                    throw new RuntimeException(e);
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
                return null;
            }
        };

        // 成功与失败回调
        downloadTask.setOnSucceeded(evt -> {
            cleanupProgressUi(rectangle, percentLabel, parentPane);
            logger.info("{} 打印组件安装程序下载完成，开始进行安装 ~", pathName);
            PluginInstalledUtil.startUpPlugin(pathName);
        });
        downloadTask.setOnFailed(evt -> {
            logger.error("{} 打印组件安装程序下载失败", pathName, downloadTask.getException());
        });
        ThreadPoolManager.getExecutorService().execute(downloadTask);
    }

    /**
     * 创建百分比标签
     */
    private static Label createPercentLabel(AnchorPane parentPane) {
        Label percentLabel = new Label("0%");
        percentLabel.setTextFill(Color.rgb(8, 191, 96));
        percentLabel.setFont(new Font(14));
        AnchorPane.setLeftAnchor(percentLabel, parentPane.getWidth() / 2);
        AnchorPane.setTopAnchor(percentLabel, (parentPane.getHeight() / 2) - 10);
        return percentLabel;
    }

    private static void cleanupProgressUi(Rectangle rectangle, Label label, AnchorPane parent) {
        rectangle.setVisible(false);
        label.setVisible(false);
        parent.getChildren().remove(label);
    }

    /**
     * 准备文件输出流
     */
    private static FileOutputStream prepareOutputStream(String pathName) throws IOException {
        File file = new File(pathName);
        if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
            throw new IOException("无法创建目录：" + file.getParent());
        }
        return new FileOutputStream(file);
    }

    /**
     * 配置 SSL 连接
     */
    private static HttpURLConnection configureSSLConnection(String downLoadUrl) throws Exception {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init((KeyStore) null);
        sslContext.init(null, tmf.getTrustManagers(), null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

        URL url = new URL(downLoadUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.connect();
        return connection;
    }

    private static void downloadFile(InputStream inputStream, FileOutputStream outputStream, int fileSize,
                                     BiConsumer<Long, Long> progressCallback, Rectangle rectangle, Label percentLabel) throws IOException {
        byte[] buffer = new byte[BUFFER_SIZE];
        long totalBytesRead = 0;
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            totalBytesRead += bytesRead;
            double progressPercent = (double) totalBytesRead / fileSize * 100;
            progressCallback.accept(totalBytesRead, (long) fileSize);
            updateMaskHeight(progressPercent, rectangle, percentLabel);
            outputStream.write(buffer, 0, bytesRead);
        }
    }

    /**
     * 更新矩形高度与进度标签文字
     */
    private static void updateMaskHeight(double progress, Rectangle rectangle, Label percentLabel) {
        Platform.runLater(() -> {
            rectangle.setHeight(96 * (100 - progress) / 100);
            percentLabel.setText(String.format("%.0f%%", progress));
        });
    }

    /**
     * 下载安装包并显示进度条窗口
     */
    public static void startDownloadProcess(String downloadUrl) {

        ProgressBar progressBar = new ProgressBar(0);
        progressBar.setPrefWidth(300);
        Label percentLabel = new Label("0%");

        StackPane progressPane = new StackPane(progressBar, percentLabel);

        Stage progressStage = new Stage();
        progressStage.setTitle(I18N.get("version.update.download"));
        progressStage.setScene(new Scene(progressPane, 350, 100));
        progressStage.setOnCloseRequest(Event::consume); // 禁止关闭
        progressStage.setResizable(false);
        progressStage.getIcons().add(new Image("image/icon.png"));
        progressStage.initOwner(GUIState.getStage());
        progressStage.initModality(Modality.APPLICATION_MODAL);
        progressStage.show();

        String pathName = CommonUtil.getCurrentDir(DOWNLOAD_DIR) + File.separator + CommonUtil.getFileNameFromUrl(downloadUrl);

        Task<Void> downloadTask = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                try (InputStream in = new URL(downloadUrl).openStream();
                     FileOutputStream out = prepareOutputStream(pathName)) {

                    int fileLength = new URL(downloadUrl).openConnection().getContentLength();
                    byte[] buffer = new byte[BUFFER_SIZE];
                    int bytesRead;
                    int totalRead = 0;

                    while ((bytesRead = in.read(buffer)) != -1) {
                        totalRead += bytesRead;
                        out.write(buffer, 0, bytesRead);
                        updateProgress(totalRead, fileLength);
                        updateMessage(String.format("%.0f%%", (double) totalRead / fileLength * 100));
                    }
                } catch (Exception e) {
                    logger.error("圆通打印助手安装包下载异常", e);
                    throw new RuntimeException(e);
                }
                return null;
            }
        };

        // 绑定 UI
        progressBar.progressProperty().bind(downloadTask.progressProperty());
        percentLabel.textProperty().bind(downloadTask.messageProperty());
        downloadTask.setOnSucceeded(evt -> {
            progressStage.close();
            logger.info("{} 圆通打印助手安装包下载完成，开始进行安装 ~", pathName);
            PluginInstalledUtil.startUpPlugin(pathName);
        });
        downloadTask.setOnFailed(evt -> {
            progressStage.close();
            logger.error("{} 圆通打印助手安装包下载失败", pathName, downloadTask.getException());
        });
        ThreadPoolManager.getExecutorService().execute(downloadTask);
    }

}
